﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;

namespace GreenArrow
{
    public class Arrow
    {
        //int tempx = 0;
        //int tempy = 0;
        //int tempwidth = 0;
        //int tempheight = 0;
        
        public bool AutoNaming = true;
        Bitmap screenBitmap;
        int markerIncrementedID = 0;
        public string DataDirectoryName = ".\\MarkerData";
        public string MarkerName = "";

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        static extern int mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);

        const int MOUSEEVENTF_MOVE = 0x0001;
        const int MOUSEEVENTF_LEFTDOWN = 0x0002;
        const int MOUSEEVENTF_LEFTUP = 0x0004;
        const int MOUSEEVENTF_RIGHTDOWN = 0x0008;
        const int MOUSEEVENTF_RIGHTUP = 0x0010;
        const int MOUSEEVENTF_MIDDLEDOWN = 0x0020;
        const int MOUSEEVENTF_MIDDLEUP = 0x0040;
        const int MOUSEEVENTF_ABSOLUTE = 0x8000;

        /*
        public Arrow() {
            DataDirectoryName = Directory.GetCurrentDirectory() + "\\MarkerData";
        }
        */
        public Arrow(string newDataDirectoryName) {
            DataDirectoryName = newDataDirectoryName;
        }
        public void TakeScreen() {
            Bitmap bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
            Graphics g = Graphics.FromImage(bmp);
            g.CopyFromScreen(0, 0, 0, 0, bmp.Size);
            g.Dispose();
            screenBitmap = bmp;
        }
        string GetNewMarkerName() {
            if (AutoNaming)
            {
                markerIncrementedID++;
                return "marker_" + string.Format("{0:D4}", markerIncrementedID);
            }
            else {
                return MarkerName;
            }
        }
        public void SendKeys(string keysToBeSent) {
            System.Windows.Forms.SendKeys.SendWait(keysToBeSent);
        }
        public string MarkRect() {
            TakeScreen();
            PickerResult result = ShowPicker(new PickerStatusGetRect());
            if (result.Canceled) {
                return "";
            }
            return SaveMarkResult(result);
        }
        string SaveMarkResult(PickerResult result) { 
            string markerName = GetNewMarkerName();
            if (! Directory.Exists(DataDirectoryName)) {
                Directory.CreateDirectory(DataDirectoryName);
            }
            string directoryName = DataDirectoryName + "\\" + markerName;
            if (! Directory.Exists(directoryName))
            {
                Directory.CreateDirectory(directoryName);
            }
            Marker newMarker = new Marker(screenBitmap);
            //tempx = result.Rects[0].Left;
            //tempy = result.Rects[0].Top;
            //tempwidth = result.Rects[0].Width;
            //tempheight = result.Rects[0].Height;
            //CopyRectFromBitmap(screenBitmap, tempx, tempy, tempwidth, tempheight).Save("x1.bmp");
            newMarker.SetPieces(result.Rects, result.Pt);
            newMarker.Save(directoryName);
            return markerName;
        }
        public Bitmap GetRect() {
            TakeScreen();
            PickerResult result = ShowPicker(new PickerStatusGetRect());
            //tempx = result.Rect.Left;
            //tempy = result.Rect.Top;
            return CopyRectFromBitmap(screenBitmap, result.Rect.Left, result.Rect.Top, result.Rect.Width, result.Rect.Height);
        }
        public static Bitmap CopyRectFromBitmap(Bitmap srcBitmap, int left, int top, int width, int height)
        {
            Bitmap bmp = new Bitmap(width, height);
            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
                    bmp.SetPixel(x, y, srcBitmap.GetPixel(left + x, top + y));
                }
            }
            return bmp;
        }
        /*
        public Bitmap CopyRectFromBitmap(Bitmap srcBitmap, int x, int y, int width, int height) {
            Bitmap bmp = new Bitmap(width, height);
            Graphics g = Graphics.FromImage(bmp);
            Rectangle destRect = new Rectangle(0, 0, width, height);
            Rectangle srcRect = new Rectangle(x, y, width, height);
            g.DrawImage(srcBitmap, destRect, srcRect, GraphicsUnit.Pixel);
            //srcBitmap.Save("t.bmp");
            return bmp;
        }*/
        PickerResult ShowPicker(PickerStatus status) {
            PickerResult result = new PickerResult();
            PickerForm pf = new PickerForm(status, result);
            pf.Width = screenBitmap.Width;
            pf.Height = screenBitmap.Height;
            pf.ImageBox.Width = screenBitmap.Width;
            pf.ImageBox.Height = screenBitmap.Height;
            pf.ImageBox.Image = screenBitmap;
            //Application.Run(pf);
            pf.ShowDialog();
            return result;
        }
        public void SendMouseClick(int x, int y) {
            mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, x * 65536 / Screen.PrimaryScreen.Bounds.Width, y * 65536 / Screen.PrimaryScreen.Bounds.Height, 0, 0);
            mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
        }
        public Point SearchRect(Bitmap bmp) {
            TakeScreen();
            //screenBitmap.Save("s.bmp");
            CompareBitmap compareBitmap = new CompareBitmap(bmp);
            int Width = screenBitmap.Width - bmp.Width;
            int Height = screenBitmap.Height - bmp.Height;
            for (int x = 0; x < Width; x++)
            {
                for (int y = 0; y < Height; y++)
                {
                    /*
                    if (x == tempx && y == tempy) {
                        Bitmap b = CopyRectFromBitmap(screenBitmap, x, y, bmp.Width, bmp.Height);
                        b.Save("b.bmp");
                    }*/
                    bool compareResult = compareBitmap.Compare(screenBitmap, x, y);
                    if (compareResult) {
                        return new Point(x, y);
                    }
                }
            }
            return new Point(-1, -1);
        }
        Point SearchPoint(Marker marker)
        {
            TakeScreen();
            CompareBitmap compareBitmap = new CompareBitmap(marker);
            int Width = screenBitmap.Width - marker.TotalWidth;
            int Height = screenBitmap.Height - marker.TotalHeight;
            for (int x = 0; x < Width; x++)
            {
                for (int y = 0; y < Height; y++)
                {
                    /*
                    if (x == tempx && y == tempy)
                    {
                        screenBitmap.Save("s.bmp");
                        CopyRectFromBitmap(screenBitmap, tempx, tempy, tempwidth, tempheight).Save("x2.bmp");
                    }
                    */
                    bool compareResult = compareBitmap.Compare(screenBitmap, x, y);
                    if (compareResult)
                    {
                        return new Point(x, y);
                    }
                }
            }
            return new Point(-1, -1);
        }
        public bool HasMarker(string markerName) {
            string markerFullPath = DataDirectoryName + "\\" + markerName;
            if(Directory.Exists(markerFullPath)){
                return true;
            }
            return false;
        }
        public bool Click(string markerName) {
            string markDirectory = DataDirectoryName + "\\" + markerName;
            Marker newMarker = Marker.Load(markDirectory);
            Point pt = SearchPoint(newMarker);
            if (pt.X != -1 && pt.Y != -1)
            {
                SendMouseClick(pt.X + newMarker.clickPoint.X, pt.Y + newMarker.clickPoint.Y);
                return true;
            }
            return false;
        }
        public bool Exists(string markerName) {
            string markDirectory = DataDirectoryName + "\\" + markerName;
            Marker newMarker = Marker.Load(markDirectory);
            Point pt = SearchPoint(newMarker);
            if (pt.X != -1 && pt.Y != -1)
            {
                return true;
            }
            return false;
        }
    }
}
